/**
 * 
 */
package sailing.db;

import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import cjlite.annotations.PostConstruct;
import cjlite.dao.DataSourceManager;
import cjlite.logger.Logger;

import com.mchange.v2.c3p0.DataSources;

/**
 * @author kevin
 * 
 */
public class DataSourceManagerImpl implements DataSourceManager {

	private static Logger logger = Logger.thisClass();
	// private String jdbcUrl = "jdbc:h2:~/sailing";
	private String jdbcUrl = "jdbc:h2:~/sailing";
	private String user = "sa";
	private String password = "";
	private String driverClass = "org.h2.Driver";

	private final String dataFolder = "data";

	private DataSource dataSource;

	@PostConstruct
	private void initialize() {
		try {
			initC3P0DataSource();
		} catch (Exception ex) {
			logger.error("error on initial datasource", ex);
		}
		testFirstConnection();
	}

	private void initC3P0DataSource() {
		try {
			//this.rebuildFileJdbcUrl();
			this.rebuildServerJdbcUrl();
			Class.forName(driverClass);
			logger.trace("JDBC URL: {0}", this.jdbcUrl);
			DataSource ds = DataSources.unpooledDataSource(jdbcUrl, user, password);
			dataSource = DataSources.pooledDataSource(ds);
		} catch (SQLException e) {
			logger.error("errot in create DataSource ({0},{1})", e, driverClass, jdbcUrl);
		} catch (ClassNotFoundException e) {
			logger.error("errot in create DataSource by driverClass[{0}]", e, driverClass);
		}
	}

	private void rebuildServerJdbcUrl() {
		StringBuilder sb = new StringBuilder("jdbc:h2:tcp://localhost/");
		String userDir = System.getProperty("user.dir");
		if (userDir.endsWith("/") || userDir.endsWith("\\")) {
			sb.append(userDir).append(dataFolder);
		} else {
			sb.append(userDir).append(File.separator).append(dataFolder);
		}
		sb.append(File.separator).append("sailing");
		jdbcUrl = sb.toString();
	}

	private void rebuildFileJdbcUrl() {
		StringBuilder sb = new StringBuilder("jdbc:h2:file:");
		String userDir = System.getProperty("user.dir");
		if (userDir.endsWith("/") || userDir.endsWith("\\")) {
			sb.append(userDir).append(dataFolder);
		} else {
			sb.append(userDir).append(File.separator).append(dataFolder);
		}
		sb.append(File.separator).append("sailing");
		jdbcUrl = sb.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see cjlite.daosupport.DataSourceManager#getDataSource()
	 */
	@Override
	public DataSource getDataSource() {
		if (dataSource == null) {
			logger.error("Current DataSource is NOT available now. Pls try to set up in 'config.properties'");
		}
		return dataSource;
	}

	private void testFirstConnection() {
		logger.entry();
		try {
			logger.debug("start to test database connection!");
			StringBuilder sb = new StringBuilder();
			Connection conn = this.dataSource.getConnection();
			DatabaseMetaData dbMetaData = conn.getMetaData();
			sb.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nusing:\n");
			
			sb.append("JDBC URL");
			sb.append("\t\t: ");
			sb.append(this.jdbcUrl);
			sb.append("\n");
			
			sb.append(dbMetaData.getDatabaseProductName());
			sb.append("\t\t\t: ");
			sb.append(dbMetaData.getDatabaseProductVersion());
			sb.append("\n");
			sb.append(dbMetaData.getDriverName());
			sb.append("\t: ");
			sb.append(dbMetaData.getDriverVersion());
			
			sb.append("JDBC Version\t\t: ");
			sb.append(dbMetaData.getJDBCMajorVersion());
			sb.append("_");
			sb.append(dbMetaData.getJDBCMinorVersion());
			sb.append("\n");

			ResultSet trs=dbMetaData.getTables(null, null, null, new String[]{"TABLE"});
			while(trs.next()){
				sb.append("table :");
				sb.append(trs.getString("TABLE_CAT"));
				sb.append("\t");
				sb.append(trs.getString("TABLE_SCHEM"));
				sb.append("\t");
				sb.append(trs.getString("TABLE_NAME"));
				sb.append("\t");
				sb.append(trs.getString("TABLE_TYPE"));
				sb.append("\n");
			}
			
			sb.append("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
			logger.logString(sb.toString());
		} catch (SQLException e) {
			logger.error("Error!!! on test database connection!! Check database infomation First", e);
		}
		logger.exit();
	}

}
